import { PrismaClient } from '@prisma/client'

interface CliOptions {
  sampleSize: number
  days: number
  includeDetails: boolean
  userIds: number[] | null
  idNumbers: string[] | null
}

interface DailySummary {
  date: string
  rewardNear: number
  rewardKrw: number
  settlements: number
  rewards: number
}

interface UserSampleResult {
  userId: number
  idNumber: string
  name: string
  tier: string
  dailySummary: DailySummary[]
  skippedDays: string[]
}

const prisma = new PrismaClient()

const parseArgs = (): CliOptions => {
  const options: CliOptions = {
    sampleSize: 10,
    days: 7,
    includeDetails: false,
    userIds: null,
    idNumbers: null
  }

  for (const arg of process.argv.slice(2)) {
    if (arg.startsWith('--sample=')) {
      const value = Number(arg.replace('--sample=', '').trim())
      if (Number.isNaN(value) || value <= 0) {
        throw new Error('无效的 --sample 值')
      }
      options.sampleSize = value
    } else if (arg.startsWith('--days=')) {
      const value = Number(arg.replace('--days=', '').trim())
      if (Number.isNaN(value) || value <= 0) {
        throw new Error('无效的 --days 值')
      }
      options.days = value
    } else if (arg === '--details') {
      options.includeDetails = true
    } else if (arg.startsWith('--userId=')) {
      const ids = arg
        .replace('--userId=', '')
        .split(',')
        .map(item => Number(item.trim()))
        .filter(id => !Number.isNaN(id))
      if (ids.length === 0) {
        throw new Error('无效的 --userId 参数')
      }
      options.userIds = ids
    } else if (arg.startsWith('--idNumber=')) {
      const idNumbers = arg
        .replace('--idNumber=', '')
        .split(',')
        .map(item => item.trim())
        .filter(item => item.length > 0)
      if (idNumbers.length === 0) {
        throw new Error('无效的 --idNumber 参数')
      }
      options.idNumbers = idNumbers
    } else {
      throw new Error(`未知参数: ${arg}`)
    }
  }

  return options
}

const formatDecimal = (value: unknown): number => {
  if (value === null || value === undefined) {
    return 0
  }
  if (typeof value === 'number') {
    return value
  }
  if (typeof value === 'bigint') {
    return Number(value)
  }
  if (typeof value === 'object') {
    const decimalLike = value as { toNumber?: () => number }
    if (typeof decimalLike.toNumber === 'function') {
      return decimalLike.toNumber()
    }
  }
  return Number(value)
}

const getTargetUsers = async (options: CliOptions): Promise<Array<{ id: number; idNumber: string; name: string; tier: string }>> => {
  if (options.userIds && options.userIds.length > 0) {
    return prisma.user.findMany({
      where: { id: { in: options.userIds } },
      select: { id: true, idNumber: true, name: true, tier: true }
    })
  }

  if (options.idNumbers && options.idNumbers.length > 0) {
    return prisma.user.findMany({
      where: { idNumber: { in: options.idNumbers } },
      select: { id: true, idNumber: true, name: true, tier: true }
    })
  }

  return prisma.user.findMany({
    where: {
      stakingInfo: {
        stakedAmount: { gt: 0 }
      }
    },
    select: {
      id: true,
      idNumber: true,
      name: true,
      tier: true
    },
    orderBy: {
      createdAt: 'desc'
    },
    take: options.sampleSize
  })
}

const collectDailySummary = async (userId: number, dayCount: number): Promise<DailySummary[]> => {
  const end = new Date()
  end.setHours(0, 0, 0, 0)

  const start = new Date(end)
  start.setDate(start.getDate() - (dayCount - 1))

  const settlements = await prisma.stakingSettlement.findMany({
    where: {
      userId,
      settlementDate: {
        gte: start,
        lt: new Date(end.getTime() + 24 * 60 * 60 * 1000)
      }
    }
  })

  const rewards = await prisma.stakingReward.findMany({
    where: {
      userId,
      createdAt: {
        gte: start,
        lt: new Date(end.getTime() + 24 * 60 * 60 * 1000)
      }
    }
  })

  const dailyMap = new Map<string, DailySummary>()

  const ensureDayEntry = (dateKey: string): DailySummary => {
    let entry = dailyMap.get(dateKey)
    if (!entry) {
      entry = {
        date: dateKey,
        rewardNear: 0,
        rewardKrw: 0,
        settlements: 0,
        rewards: 0
      }
      dailyMap.set(dateKey, entry)
    }
    return entry
  }

  for (const settlement of settlements) {
    const dateKey = settlement.settlementDate.toISOString().substring(0, 10)
    const entry = ensureDayEntry(dateKey)
    entry.rewardNear += formatDecimal(settlement.rewardNear)
    entry.rewardKrw += formatDecimal(settlement.rewardKrw)
    entry.settlements += 1
  }

  for (const reward of rewards) {
    const dateKey = reward.createdAt.toISOString().substring(0, 10)
    const entry = ensureDayEntry(dateKey)
    entry.rewards += 1
  }

  const summaries: DailySummary[] = []
  for (let offset = dayCount - 1; offset >= 0; offset--) {
    const day = new Date(end)
    day.setDate(day.getDate() - offset)
    const key = day.toISOString().substring(0, 10)
    const entry = dailyMap.get(key) ?? {
      date: key,
      rewardNear: 0,
      rewardKrw: 0,
      settlements: 0,
      rewards: 0
    }
    entry.rewardNear = Math.round(entry.rewardNear * 10000) / 10000
    entry.rewardKrw = Math.round(entry.rewardKrw * 100) / 100
    summaries.push(entry)
  }

  return summaries
}

const identifySkippedDays = (dailySummary: DailySummary[]): string[] => {
  return dailySummary
    .filter(day => day.settlements === 0 && day.rewards === 0)
    .map(day => day.date)
}

const main = async (): Promise<void> => {
  const options = parseArgs()
  const users = await getTargetUsers(options)

  if (users.length === 0) {
    console.log('未找到符合条件的用户。')
    return
  }

  const results: UserSampleResult[] = []

  for (const user of users) {
    try {
      const dailySummary = await collectDailySummary(user.id, options.days)
      const skippedDays = identifySkippedDays(dailySummary)

      results.push({
        userId: user.id,
        idNumber: user.idNumber,
        name: user.name,
        tier: user.tier,
        dailySummary,
        skippedDays
      })
    } catch (error) {
      console.error(`获取用户 ${user.id} 的收益数据失败:`, error)
    }
  }

  const summary = {
    sampledUsers: results.length,
    days: options.days,
    usersWithSkippedDays: results.filter(item => item.skippedDays.length > 0).length,
    results: results.map(item => ({
      userId: item.userId,
      idNumber: item.idNumber,
      name: item.name,
      tier: item.tier,
      skippedDays: item.skippedDays,
      dailySummary: options.includeDetails ? item.dailySummary : undefined
    }))
  }

  console.log(JSON.stringify(summary, null, 2))
}

main().catch(async error => {
  console.error('抽样质押收益脚本执行失败:', error)
  await prisma.$disconnect()
  process.exit(1)
}).finally(async () => {
  await prisma.$disconnect()
})
